#include "Creature.h"
#include <set>
#include <queue>

using namespace cmn;

Creature::Creature() :
	m_head( 0 ),
	m_partsCount( 0 ),
	m_parts( Graph<IPart*>::GraphType::Undirected )
{}

Creature::~Creature()
{}

void Creature::AddPart( IPart* part ) {
	if( m_partsCount == 0 )
		m_head = part;
	m_parts.AddNode( part );
	m_partsCount++;
}

void Creature::RemovePart( IPart* part ) {
	if( part == m_head )
		m_head = 0;
	m_parts.RemoveNode( part );
	m_partsCount--;
}

void Creature::ProcessCommand( const Command& command ) {
	std::set<IPart*> set;

	std::queue<IPart*> queue;
	queue.push( m_head );
	while( !queue.empty() ) {
		IPart* part = queue.front();
		queue.pop();
		part->ProcessCommand( command );

		for( IteratorPtr<IPart*> neighbors( m_parts.GetNeihgbors( part ) );
				!neighbors.IsEnd();
				neighbors.Next() )
		{
			IPart* nextPart = neighbors.Current();
			if( set.find( nextPart ) == set.end() ) {
				set.insert( nextPart );
				queue.push( nextPart );
			}
		}
	}
	set.clear();
}

void Creature::Update( float dt ) {
	for( IteratorPtr<IPart*> parts( m_parts.GetNodes() );
			!parts.IsEnd();
			parts.Next() )
	{
		parts.Current()->Update( dt );
	}
}

void Creature::Draw() const {
	for( IteratorPtr<IPart*> parts( m_parts.GetNodes() );
			!parts.IsEnd();
			parts.Next() )
	{
		parts.Current()->Draw();
	}
}

void Creature::LinkParts( IPart* partA, IPart* partB ) {
	m_parts.SetLinked( partA, partB, true );
}

void Creature::UnlinkParts( IPart* partA, IPart* partB ) {
	m_parts.SetLinked( partA, partB, false );
}

const IIterable<IPart*>* Creature::GetParts() {
	return m_parts.GetNodes();
}

